#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#define handle_error(msg)   \
    do                      \
    {                       \
        perror(msg);        \
        exit(EXIT_FAILURE); \
    } while (0)

int main(int argc, char *argv[])
{
    char *addr;
    int fd;
    int i;
    struct stat sb;
    off_t offset, pa_offset;
    size_t length;
    ssize_t s;
    char *buf = "123456789abcdefghijkl";

    // if (argc < 3 || argc > 4)
    // {
    //     fprintf(stderr, "%s file offset [length]\n", argv[0]);
    //     exit(EXIT_FAILURE);
    // }

    // fd = open(argv[1], O_RDWR);
    fd = open("b.data", O_RDWR);
    if (fd == -1)
        handle_error("open");

    if (fstat(fd, &sb) == -1)
        handle_error("fstat");

    // offset = atoi(argv[2]);
    offset = 3;
    pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);

    if (offset >= sb.st_size)
    {
        fprintf(stderr, "offset is past end if file \n");
        exit(EXIT_FAILURE);
    }

    if (argc == 4)
    {
        // length = atoi(argv[3]);
        length = 10;
        if (offset + length > sb.st_size)
            length = sb.st_size - offset;
    }
    else
    {
        length = sb.st_size - offset;
    }

    printf("\tfile size is %d\n", sb.st_size);
    printf("length = %d\t, mapped memory length = %d\t, pa_offset = %d\n", length, length + offset - pa_offset, pa_offset);
    addr = mmap(NULL, length + offset - pa_offset, PROT_READ | PROT_WRITE,
                MAP_SHARED, fd, pa_offset);

    if (addr == MAP_FAILED)
        handle_error("mmap");

    memcpy(addr, buf, 10);
    printf("check write!\n");
    for (i = 0; i < 10; i++)
    {
        printf("new mem[%d] = %c\n", i, *(addr + i));
    }

    printf("string test = %s\n", (char *)addr);

    munmap(addr, length + offset - pa_offset);
    return 0;
}